﻿using System;
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Routing;

namespace FBGraph.Web.Mvc
{
    /// <summary>Extensions to assist with rendering Graph API objects and values to HTML.</summary>
    public static class HtmlHelperExtensions
    {
        /// <summary>Renders <paramref name="value" /> with the specified <paramref name="prefix" /> if <paramref name="value" /> is a not a null reference.</summary>
        /// <param name="html">The <see cref="HtmlHelper" />.</param>
        /// <param name="value">The value to render.</param>
        /// <param name="prefix">The prefix to prepend to the string representation of the value.</param>
        /// <returns>A <see cref="String" /> representation of <paramref name="value" /> prepended by <paramref name="prefix" /> if <paramref name="value" /> is not a null
        /// reference; otherwise, an empty string.</returns>
        public static String Prefix(this HtmlHelper html, Object value, String prefix)
        {
            if (value == null) return String.Empty;
            return String.Format("{0}{1}", prefix, value);
        }

        /// <summary>Renders <paramref name="value" /> wrapped the specified <paramref name="htmlElement" /> if <paramref name="value" /> is a not a null reference.</summary>
        /// <param name="html">The <see cref="HtmlHelper" />.</param>
        /// <param name="value">The value to render.</param>
        /// <param name="htmlElement">The HTML element with which to wrap the value (for example, <c>p</c>, <c>div</c>, or <c>span</c>).</param>
        /// <returns>A <see cref="String" /> representation of <paramref name="value" /> wrapped in html if <paramref name="value" /> is not a null
        /// reference; otherwise, an empty string.</returns>
        public static String Wrap(this HtmlHelper html, Object value, String htmlElement)
        {
            return html.Wrap(value, htmlElement, null);
        }

        /// <summary>Renders <paramref name="value" /> wrapped the specified <paramref name="htmlElement" /> if <paramref name="value" /> is a not a null reference.</summary>
        /// <param name="html">The <see cref="HtmlHelper" />.</param>
        /// <param name="value">The value to render.</param>
        /// <param name="htmlElement">The HTML element with which to wrap the value (for example, <c>p</c>, <c>div</c>, or <c>span</c>).</param>
        /// <param name="htmlAttributes">An object defining html attributes to apply to the generated HTML wrapper.</param>
        /// <returns>A <see cref="String" /> representation of <paramref name="value" /> wrapped in html if <paramref name="value" /> is not a null
        /// reference; otherwise, an empty string.</returns>
        public static String Wrap(this HtmlHelper html, Object value, String htmlElement, Object htmlAttributes)
        {
            return html.Wrap(value, htmlElement, new RouteValueDictionary(htmlAttributes));
        }

        /// <summary>Renders <paramref name="value" /> wrapped the specified <paramref name="htmlElement" /> if <paramref name="value" /> is a not a null reference.</summary>
        /// <param name="html">The <see cref="HtmlHelper" />.</param>
        /// <param name="value">The value to render.</param>
        /// <param name="htmlElement">The HTML element with which to wrap the value (for example, <c>p</c>, <c>div</c>, or <c>span</c>).</param>
        /// <param name="htmlAttributes">A dictionary defining html attributes to apply to the generated HTML wrapper.</param>
        /// <returns>A <see cref="String" /> representation of <paramref name="value" /> wrapped in html if <paramref name="value" /> is not a null
        /// reference; otherwise, an empty string.</returns>
        public static String Wrap(this HtmlHelper html, Object value, String htmlElement, IDictionary<String, Object> htmlAttributes)
        {
            if (value == null) return String.Empty;
            else
            {
                var tag = new TagBuilder(htmlElement);
                tag.MergeAttributes(htmlAttributes);
                tag.InnerHtml = value.ToString();
                return tag.ToString();
            }
        }

        /// <summary>Renders an <c>img</c> tag for the picture of the specific Graph API object.</summary>
        /// <param name="html">A reference to an <see cref="HtmlHelper" /> object.</param>
        /// <param name="pictureUrl">The url of the objects picture, if it is available.</param>
        /// <param name="id">The id of the Graph API object whose picture will be displayed.</param>
        /// <param name="alt">The alt text for the picture.</param>
        /// <returns>An <c>img</c> tag for the picture of the specific Graph API object.</returns>
        /// <remarks>If <paramref name="pictureUrl" /> is null, the url for the object's picture connection will automatically be generated.</remarks>
        public static String Picture(this HtmlHelper html, String pictureUrl, Object id, String alt)
        {
            var tag = new TagBuilder("img");
            tag.Attributes.Add("alt", alt);
            tag.Attributes.Add("src", pictureUrl ?? html.FbContext().CreateRequestUri("picture", null, id).ToString());

            return tag.ToString();
        }

        /// <summary>Renders an <c>img</c> tag for the picture of the specific Graph API object.</summary>
        /// <param name="html">A reference to an <see cref="HtmlHelper" /> object.</param>
        /// <param name="id">The id of the Graph API object whose picture will be displayed.</param>
        /// <param name="alt">The alt text for the picture.</param>
        /// <returns>An <c>img</c> tag for the picture of the specific Graph API object.</returns>
        public static String Picture(this HtmlHelper html, Object id, String alt)
        {
            return html.Picture(null, id, alt);
        }

        private static IFBGraphHttpContext FbContext(this HtmlHelper html)
        {
            var controller = html.ViewContext.Controller as FBGraphMvcController;
            if (controller == null) return null;
            else return controller.FbContext;
        }
    }
}